package cn.kimming.wms.dao.impl;

import java.lang.reflect.ParameterizedType;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;

import cn.kimming.wms.dao.IGenericDAO;
import cn.kimming.wms.query.QueryObject;

public class GenericDAOImpl<T> implements IGenericDAO<T> {

	private Class<T> genericType;

	public GenericDAOImpl() {
		ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
		genericType = (Class<T>) pt.getActualTypeArguments()[0];
	}

	@Autowired
	protected SessionFactory sessionFactory;

	@Override
	public void save(T e) {
		Session session = sessionFactory.getCurrentSession();
		sessionFactory.getCurrentSession().getTransaction().isActive();
		session.save(e);
	}

	@Override
	public void update(T e) {
		Session session = sessionFactory.getCurrentSession();
		session.update(e);
	}

	@Override
	public void delete(T obj) {
		Session session = sessionFactory.getCurrentSession();
		session.delete(obj);
	}

	@Override
	public T get(Long id) {
		Session session = sessionFactory.getCurrentSession();
		return (T) session.get(genericType, id);
	}

	@Override
	public List<T> list() {
		Session session = sessionFactory.getCurrentSession();
		return session.createCriteria(genericType).setCacheable(true).list();
	}

	public List<T> query(QueryObject qo) {
		Session session = sessionFactory.getCurrentSession();
		//1.查询结果记录总数
		String hql = "select COUNT(obj) from " + genericType.getSimpleName() + " obj" + qo.getQuery();
		Query query = session.createQuery(hql);
		setPlaceHolder(query, qo);
		qo.setTotal(((Long)query.uniqueResult()).intValue());
		//2.查询实体结果集
		hql = "select obj from " + genericType.getSimpleName() + " obj" + qo.getQuery();
		query = session.createQuery(hql);
		setPlaceHolder(query, qo);
		//设置分页参数
		query.setFirstResult((qo.getCurrentPage() -1) * qo.getPageSize()).setMaxResults(qo.getPageSize());
		return query.list();
	}

	private void setPlaceHolder(Query query, QueryObject qo) {
		for (int i = 0; i < qo.getParams().size(); i++) {
			query.setParameter(i, qo.getParams().get(i));
		}
	}

	@Override
	public List<T> queryForList(String condition, Object... args) {
		Session session = sessionFactory.getCurrentSession();
		StringBuilder hql = new StringBuilder(80);
		hql.append("select obj from ").append(genericType.getSimpleName()).append(" obj");
		if (StringUtils.isNotEmpty(condition)) {
			hql.append(" where ").append(condition);
		}
		Query query = session.createQuery(hql.toString());
		for (int i = 0; i < args.length; i++) {
			query.setParameter(i, args[i]);
		}
		return query.list();
	}

	@Override
	public T queryForObject(String condition, Object... args) {
		return queryForList(condition,args).size() == 1 ? queryForList(condition,args).get(0) : null;
	}


}
